package com.neusoft.neuiotms.dcam.fixed.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.bizcore.web.utils.EasyPoiStylerColorImpl;
import com.neusoft.neuiotms.dcam.constant.DCAMConsts;
import com.neusoft.neuiotms.dcam.fixed.converter.StockConverter;
import com.neusoft.neuiotms.dcam.fixed.dto.StockDTO;
import com.neusoft.neuiotms.dcam.fixed.model.Stock;
import com.neusoft.neuiotms.dcam.fixed.repository.StockRepository;
import com.neusoft.neuiotms.dcam.fixed.service.StockService;
import com.neusoft.neuiotms.dcam.fixed.vo.StockExportVO;
import com.neusoft.neuiotms.dcam.fixed.vo.StockQueryExportVO;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import lombok.Getter;
import lombok.Setter;

@Service
public class StockServiceImpl implements StockService {

    @Autowired
    private StockRepository stockRepository;

    @Autowired
    private StockConverter stockConverter;

    @Override
    public StockDTO create(final StockDTO dto) {
        Stock model = null;
        if (dto != null) {
            model = this.stockConverter.toModel(dto);
            model.setStatus(DCAMConsts.STOCK_STATUS_NEW);
            model = this.stockRepository.save(model);
        }
        return this.stockConverter.toDTO(model);
    }

    @Override
    public void delete(final Long id) {
        this.stockRepository.deleteById(id);
    }

    @Override
    public StockDTO update(final Long id, final StockDTO dto) {
        Stock model = null;
        try {
            if (dto != null) {
                model = this.stockRepository.getOne(id);

                if (model != null) {
                    dto.setId(model.getId());
                    model = this.stockConverter.toModel(dto);
                    model.setStatus(DCAMConsts.STOCK_STATUS_NEW);
                    this.stockRepository.save(model);
                }
            }

        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        return this.stockConverter.toDTO(model);
    }

    @Override
    public List<StockDTO> findAll() {
        List<Stock> models = this.stockRepository.findAll();
        if (models != null) {
            models = models.parallelStream().filter(r -> DCAMConsts.STOCK_STATUS_NEW.equals(r.getStatus()))
                    .collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(models)) {
            return this.stockConverter.toListDTO(models);
        }
        return null;
    }

    @Override
    public StockDTO details(final Long id) {
        if (id == null) {
            return null;
        }
        final Stock model;
        try {
            model = this.stockRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        return this.stockConverter.toDTO(model);
    }

    @Override
    public Page<StockDTO> search(final Pageable pageable, final Searchable searchable) {
        //        searchable.put("status",DCAMConsts.STOCK_STATUS_NEW);
        final Page<Stock> result = this.stockRepository.search(pageable, searchable);
        return this.stockConverter.toPageDTO(result);
    }

    @Override
    public Workbook export(final Searchable searchable, final Pageable pageable) {
        final Page<Stock> models = this.stockRepository.search(pageable, searchable);
        final List<StockExportVO> list = new ArrayList<>(models.getSize() == 0 ? 1 : models.getSize());
        models.forEach(model -> {
            list.add(this.stockConverter.toVO(model));
        });
        final ExportParams param = new ExportParams("库存导出", "库存导出", ExcelType.XSSF);
        param.setStyle(EasyPoiStylerColorImpl.class);

        return ExcelExportUtil.exportExcel(param, StockExportVO.class, list);
    }

    @Override
    public Workbook downloadStockQuery(final Searchable searchable, final Pageable pageable) {
        final Page<Stock> models = this.stockRepository.search(pageable, searchable);
        final List<StockQueryExportVO> list = new ArrayList<>(models.getSize() == 0 ? 1 : models.getSize());
        models.forEach(model -> {
            list.add(this.stockConverter.toStockQueryVO(model));
        });
        final ExportParams param = new ExportParams("库存查询结果导出", "库存查询结果导出", ExcelType.XSSF);
        param.setStyle(EasyPoiStylerColorImpl.class);

        return ExcelExportUtil.exportExcel(param, StockQueryExportVO.class, list);
    }

    @Override
    public StockDTO updateStockNum(final Long id, final int num) {

        final Stock model;
        try {
            model = this.stockRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        //model.setNumber(model.getNumber() + num);
        this.stockRepository.save(model);
        return this.stockConverter.toDTO(model);
    }

    @Override
    public Workbook exportReport(Searchable searchable) {
        final List<Stock> result = this.stockRepository.search(searchable);

        final List<StockReportVO> list = new ArrayList<>(result.size() == 0 ? 1 : result.size());
        result.stream().map(t -> {
            final StockReportVO vo = new StockReportVO();
            vo.setStorckNumber(t.getStorckNumber());
            vo.setSpareTypeName(t.getSpareType().getName());
            vo.setSpecification(t.getSpecification());
            vo.setSn(t.getSn());
            vo.setSource(
                    "new".equals(t.getSource()) ? "合同采购" : ("back".equals(t.getSource()) ? "退库利旧" : t.getSource()));
            vo.setContractName(t.getContract().getName());
            vo.setUnitPrice(t.getUnitPrice());
            vo.setCreateTime(DateFormatUtils.format(t.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            vo.setUpdateTime(
                    "used".equals(t.getStatus()) ? DateFormatUtils.format(t.getUpdateTime(), "yyyy-MM-dd HH:mm:ss")
                            : "");
            return vo;
        }).forEach(list::add);

        final ExportParams param =
                new ExportParams("备品备件出入库统计", "备品备件出入库统计", ExcelType.XSSF);
        param.setStyle(EasyPoiStylerColorImpl.class);
        return ExcelExportUtil.exportExcel(param, StockReportVO.class, list);
    }

    @Setter
    @Getter
    static class StockReportVO {

        @Excel(name = "货品编号", orderNum = "0", width = 30)
        private Object storckNumber;

        @Excel(name = "分类", orderNum = "1", width = 30)
        private Object spareTypeName;

        @Excel(name = "规格型号", orderNum = "2", width = 30)
        private Object specification;

        @Excel(name = "SN码", orderNum = "3", width = 30)
        private Object sn;

        @Excel(name = "备品来源", orderNum = "4", width = 30)
        private Object source;

        @Excel(name = "关联合同", orderNum = "5", width = 30)
        private Object contractName;

        @Excel(name = "单价（元）", orderNum = "6", width = 30)
        private Object unitPrice;

        @Excel(name = "入库时间", orderNum = "7", width = 30)
        private Object createTime;

        @Excel(name = "出库时间", orderNum = "8", width = 30)
        private Object updateTime;

    }

}
